// AlgorithmLink.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "AlgorithmLink.h"
//#include "PointerLink.h"
#include "CycleCompare.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// The one and only application object

CWinApp theApp;

//#include < iostream > 
#include < list > 
#include <map>
#include <set>

using namespace std;

void TestLinkList(void);

void TestReduplicateList(void);

void PrintStringArray(CStringArray& oCycleArray);

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	HMODULE hModule = ::GetModuleHandle(NULL);

	if (hModule != NULL)
	{
		// initialize MFC and print and error on failure
		if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		{
			// TODO: change error code to suit your needs
			_tprintf(_T("Fatal Error: MFC initialization failed\n"));
			nRetCode = 1;
		}
		else
		{
			// TODO: code your application's behavior here.
            //TestLinkList();
            TestReduplicateList();

            system("pause");
		}
	}
	else
	{
		// TODO: change error code to suit your needs
		_tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
		nRetCode = 1;
	}

	return nRetCode;
}

CString FormatCycleString( const CString& strCycleString, list<CString> &lstCycle )
{
    CString strRet, strTemp, strLeft, strRight;
    CString strLeadingCharacter = _T(" ");
    CString strCurrSep = _T("\n");
    int nPos = 0, nNums = 0, nSepLen = 0;

    strTemp.Format( _T("%s"), strCycleString );

    while (nPos != -1)
    {
        nSepLen = strCurrSep.GetLength();

        nPos = strTemp.Find(strCurrSep);

        // If do not find the separator break;
        if (nPos == -1)
        {
            //strLeft = strTemp;
            break;
        }

        nNums ++;

        strLeft = strTemp.Left( nPos + nSepLen );
        //strRight.Append( CString(_T(' '), nNums) );
        strRight.Format( _T("%s%s"), CString(_T(' '), nNums), strTemp.Mid(nPos + nSepLen, strCycleString.GetLength()) );
        strTemp = strRight;
        strRight.Empty();

        strRet += strLeft;

        strLeft.TrimRight(strCurrSep);
        lstCycle.push_back(strLeft);

        //rVctStringList.push_back(strLeft.Mid(nDelimiterLen, strLeft.GetLength() - 2 * nDelimiterLen));
    }

    strTemp.TrimRight(strCurrSep);
    lstCycle.push_back(strTemp);

    if( (nNums == 0) && (nPos == -1) )
    {
        strRet = strTemp;
    }

    if (nNums)
    {
        strRet += strTemp;
    }

    return strRet;
}

void TestReduplicateList(void)
{
    CCycleCompare oCycle;
    std::multimap<CString, CString> mapCycle;
    oCycle.GenerateCycleLink( mapCycle );

    CStringArray oCycleArray;
    oCycle.GetUniqueCycleData(oCycleArray);

    cout << "\n\n\t Found cycles: " << endl;
    PrintStringArray(oCycleArray);
}

void TestLinkList(void)
{
    std::multimap<CString, CString> mapCycle;
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP4\nP1"));
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP1"));
    mapCycle.insert(pair<CString, CString>("P2", "P2\nP3\nP1\nP4\nP2"));
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP4\nP1"));
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP4\nP1"));
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP4\nP1"));
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP4\nP1"));
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP4\nP1"));
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP4\nP1"));
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP4\nP1"));
    mapCycle.insert(pair<CString, CString>("P3", "P3\nP2\nP4\nP1\nP3"));
    mapCycle.insert(pair<CString, CString>("P4", "P1\nP3\nP2\nP4\nP1"));
    mapCycle.insert(pair<CString, CString>("P1", "P1\nP3\nP2\nP4\nP1"));

    std::multimap<CString, CString>::iterator  iter;
    list<CCycleDataNode> lstCycleData;

    CString strRoot, strPath;
    for(iter = mapCycle.begin(); iter != mapCycle.end(); iter++)
    {
        cout << CStringA(iter->first) <<"   "<< CStringA(iter->second) << endl;
        strRoot = iter->first;
        strPath = iter->second;
        cout << CStringA(strRoot) <<"   "<< CStringA(strPath) << endl;

        list<CString> oLinkList;

        FormatCycleString(iter->second, oLinkList);

        CCycleDataNode oCycleDataNode( strRoot, strPath, oLinkList );
        lstCycleData.push_back(oCycleDataNode);
    }

    //int c = 0;
    //CPointerLink<int> duLinkList(c);
    //int d=2;
    //int e=3;
    //int f=4;
    //int g=5;
    //int h=6;
    //int i=7;
    //duLinkList.add(d);
    //duLinkList.add(e);
    //duLinkList.add(f);
    //duLinkList.add(g);
    //duLinkList.add(h);
    //duLinkList.add(i);
    //duLinkList.print();
    //cout << "Lenth of DuLink: " << duLinkList.length << endl;

    //if( -1 == duLinkList.DelElem(6) ){
    //    cout << "fail to delete element " << endl;
    //}
    //duLinkList.print();
    //cout << "lenth of DuLink: " << duLinkList.length << endl;

}

void PrintStringArray(CStringArray& oCycleArray)
{
    for (int i = 0; i < oCycleArray.GetCount(); i++)
    {
        cout << "\t" << CStringA(oCycleArray[i]) << endl; // free objects before resetting array size.         
    }
}
